package ksj.common.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class DateUtil {

	public static Date toDate(String dateStr) throws Exception {
		// TODO date format unify
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		try {
			Date receivingDate = dateFormat.parse(dateStr);
			return receivingDate;
		} catch (ParseException e) {
			throw new Exception(e);
		}
	}

	public static Date toDateForMonthDate(String dateStr) throws Exception {
		// TODO date format unify
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM");
		try {
			Date receivingDate = dateFormat.parse(dateStr);
			return receivingDate;
		} catch (ParseException e) {
			throw new Exception(e);
		}
	}

	public static Date toDate(String dateStr, String datePattern) throws Exception {
		// TODO date format unify
		DateFormat dateFormat = new SimpleDateFormat(datePattern);
		try {
			Date receivingDate = dateFormat.parse(dateStr);
			return receivingDate;
		} catch (ParseException e) {
			System.out.println(dateStr);
			throw new Exception(e);
		}

	}

	public static String toString(Date date) {
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		return dateFormat.format(date);
	}

	public static String toStringForMonth(Date date) {
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM");
		return dateFormat.format(date);
	}

	public static String toString(Date date, String datePattern) {

		DateFormat dateFormat = new SimpleDateFormat(datePattern);
		return dateFormat.format(date);
	}

	public static String toStringYYYYMMDD(Date date) {

		DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
		return dateFormat.format(date);
	}

	public static String toStringYYYYMM(Date date) {

		DateFormat dateFormat = new SimpleDateFormat("yyyyMM");
		return dateFormat.format(date);
	}

	public static List<Date> getDateArrayByRange(Date startDate, Date endDate) {
		int days;
		try {
			days = daysBetween(startDate, endDate);
		} catch (ParseException e) {
			return new ArrayList<Date>();
		}
		List<Date> dateList = new ArrayList<Date>();
		for (int i = 0; i <= days; i++) {
			dateList.add(getDateAfter(startDate, i));
		}

		return dateList;
	}

	public static List<Date> getMonthDateArrayByRange(Date startDate, Date endDate) {
		int months;
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
			startDate = sdf.parse(sdf.format(startDate));
			endDate = sdf.parse(sdf.format(endDate));
			months = monthsBetween(startDate, endDate);
		} catch (ParseException e) {
			return new ArrayList<Date>();
		}
		List<Date> monthDateList = new ArrayList<Date>();
		for (int i = 0; i <= months; i++) {
			monthDateList.add(getMonthDateAfter(startDate, i));
		}
		return monthDateList;
	}

	private static int monthsBetween(Date startDate, Date endDate) throws ParseException {
		long monthday;
		Calendar starCal = Calendar.getInstance();
		starCal.setTime(startDate);
		int sYear = starCal.get(Calendar.YEAR);
		int sMonth = starCal.get(Calendar.MONTH);
		Calendar endCal = Calendar.getInstance();
		endCal.setTime(endDate);
		int eYear = endCal.get(Calendar.YEAR);
		int eMonth = endCal.get(Calendar.MONTH);
		monthday = ((eYear - sYear) * 12 + (eMonth - sMonth));
		return Integer.parseInt(String.valueOf(monthday));
	}

	private static Date getMonthDateAfter(Date d, int month) {
		Calendar now = Calendar.getInstance();
		now.setTime(d);
		now.set(Calendar.MONTH, now.get(Calendar.MONTH) + month);
		return now.getTime();
	}

	private static int daysBetween(Date smdate, Date bdate) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		smdate = sdf.parse(sdf.format(smdate));
		bdate = sdf.parse(sdf.format(bdate));
		Calendar cal = Calendar.getInstance();
		cal.setTime(smdate);
		long time1 = cal.getTimeInMillis();
		cal.setTime(bdate);
		long time2 = cal.getTimeInMillis();
		long between_days = (time2 - time1) / (1000 * 3600 * 24);

		return Integer.parseInt(String.valueOf(between_days));
	}

	public static Date getDateAfter(Date d, int day) {
		Calendar now = Calendar.getInstance();
		now.setTime(d);
		now.set(Calendar.DATE, now.get(Calendar.DATE) + day);
		return now.getTime();
	}

	public static Date getFirstDayofLastMonth(String stringformat) {
		SimpleDateFormat format = new SimpleDateFormat(stringformat);
		Calendar aCalendar = Calendar.getInstance();
		// add -1 month to current month
		aCalendar.add(Calendar.MONTH, -1);
		// set DATE to 1, so first date of previous month
		aCalendar.set(Calendar.DATE, 1);

		Date firstDateOfPreviousMonth = Utility.stringToDate(format.format(aCalendar.getTime()), stringformat);

		return firstDateOfPreviousMonth;
	}
	
	public static Date getFirstDayofCurrentMonth(String stringformat) {
		SimpleDateFormat format = new SimpleDateFormat(stringformat);
		Calendar aCalendar = Calendar.getInstance();
		// add -1 month to current month
		aCalendar.add(Calendar.MONTH, 0);
		// set DATE to 1, so first date of previous month
		aCalendar.set(Calendar.DATE, 1);

		Date firstDateOfPreviousMonth = Utility.stringToDate(format.format(aCalendar.getTime()), stringformat);

		return firstDateOfPreviousMonth;
	}

	public static Date getLastDayofLastMonth(String stringformat) {
		SimpleDateFormat format = new SimpleDateFormat(stringformat);
		Calendar aCalendar = Calendar.getInstance();
		// add -1 month to current month
		aCalendar.add(Calendar.MONTH, -1);
		// set DATE to 1, so first date of previous month
		aCalendar.set(Calendar.DATE, 1);

		// set actual maximum date of previous month
		aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		// read it
		Date lastDateOfPreviousMonth = Utility.stringToDate(format.format(aCalendar.getTime()), stringformat);
		return lastDateOfPreviousMonth;
	}

	public static Date getDateAfter(int years, int months, int days) {
		Date date = new Date();
		Calendar now = Calendar.getInstance();
		now.setTime(date);
		now.set(Calendar.YEAR, now.get(Calendar.YEAR) + years);
		now.set(Calendar.MONTH, now.get(Calendar.MONTH) + months);
		now.set(Calendar.DATE, now.get(Calendar.DATE) + days);
		return now.getTime();
	}

	public static boolean isInDateRange(Date verifyDate, Date startDate, Date endDate) {
		return (verifyDate.before(endDate) && verifyDate.after(startDate)) || verifyDate.equals(startDate)
				|| verifyDate.equals(endDate);
	}

	public static Date yestedayDate() {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		return calendar.getTime();
	}

	public static Date getSuguoLimitDate() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.YEAR, 2014);
		calendar.set(Calendar.MONTH, 5);
		calendar.set(Calendar.DAY_OF_MONTH, 10);
		return calendar.getTime();
	}

	/**
	 * 获取包含完整一周的所有周一
	 * 
	 * @param dates
	 *            所有有序日期
	 * @param beforeToday
	 *            只返回今天之前包含完整一周的周一
	 * @return
	 */
	public static List<Date> getWeekFirstDatesWithWholeWeek(List<Date> dates, boolean beforeToday) {
		List<Date> d = new ArrayList<Date>();
		if (dates == null || dates.size() < 7) {
			return d;
		}
		Date DateBegin = dates.get(0);
		int week = getWeekDayByDate(DateBegin);
		int index = 0;
		if (week != 1) {
			index = 8 - week;
		}
		while (index + 7 <= dates.size()) {
			d.add(dates.get(index));
			index += 7;
		}
		if (d.size() > 0 && beforeToday && getDateAfter(d.get(d.size() - 1), 6).after(new Date())) {
			d.remove(d.size() - 1);
		}
		return d;
	}

	/**
	 * 获取星期几
	 * 
	 * @param date
	 * @return
	 */
	public static int getWeekDayByDate(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int week = calendar.get(Calendar.DAY_OF_WEEK);
		if (--week == 0)
			week = 7;
		return week;
	}

}
